汇编语言课程设计一完整代码及详细解析
建议先自己思考问题的答案,不懂则返回看书
第二列需要用除法的溢出公式计算,第三列需要32/16 位的除法,第四列需要16/8位的除法。详细解析看代码注释。
assume cs:code
data segment
db '1975','1976','1977','1978','1979','1980','1981','1982','1983','1984','1985'
db '1986','1987','1988','1989','1990','1991','1992','1993','1994','1995'
;db占21*4Byte 0-83
dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514,345980
dd 590827,803530,1183000,1843000,2758000,3753000,4649000,5937000
;dd型数据,需要两个寄存器存放 占21*4Byte 84-167
;0010计算机中低字节存放高位00h,高字节存放低位10h
dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
dw 11542,14430,15257,17800
;dw占21*2Byte 168-209
data ends
temp segment
dw 24 dup (0)
temp ends
table segment
db 21 dup ('year r e s ',0)
table ends
stack segment
dw 32 dup(0)
stack ends
;1.用第二、三列的值计算得到第四列的值。。计算到哪
;2.将第二、三、四列的值转换为十进制字符串。。转换后存在哪
;3.按格式显示。。格式如何安排
code segment
start:
mov ax,data
mov ds,ax
mov si,84
mov di,168
mov bx,table
mov es,bx
mov bx,28 ;ds,si,di,es,bx,是此函数中的全局变量,28是table中存放salary的列号
call divsalary ;此函数结束,第四列的值计算完毕,十进制存在table中
call moveyear ;此函数结束,year的值移到table中的相应位置
call revenue ;此函数结束,利润的值移到table中
call employee ;此函数结束,员工数复制到table中
call showstr ;显示所有信息
mov ax,4c00h
int 21h
;计算第四列的值,并将第四列的值存放在table段中
divsalary:
push ax
push bx
push cx
push dx
push ds
push si
push di
push es
mov cx,21 ;21次计算
divs:
push cx
mov ax,ds:[si] ;低位在ax中
mov dx,ds:[si+2] ;高位在dx中
add si,4 ;指向下一个dd型数据
mov cx,ds:[di]
div cx
; div word ptr ds:[di] ;结果,得到需要的值在ax中
add di,2 ;指向下一个dw型数据
call divDtoc
pop cx
loop divs
pop es
pop di
pop si
pop ds
pop dx
pop cx
pop bx
pop ax
ret
;将divsalary内计算得到的薪水ax的值显示为十进制存放在table中的第四数值列
divDtoc:
push cx
push si
;进入此函数时未改变ax的值
;由图知第四列最大值333=14DH,采用8位除法,不会溢出
;8位除法,被除数ax中,结果AL商,AH余数
;进入此函数时未改变ax的值,即ax就是被除数
mov si,0
mov bp,0
mov cx,0
mov dx,10
divDtocs:
div dl ;结果AL商,AH余数
mov cl,al ;先把商保存在cl中
mov al,0
add ah,30h
push ax ;把余数在栈中保存,但此时余数在高位,弹出时留意
inc bp ;用bp对位数计数
jcxz divDtocOver
mov ax,cx ;覆盖AH的值,ch是零
jmp short divDtocs
divDtocOver: ;分离结束,准备存放
mov cx,bp ;bp对位数计数,即push次数、需pop次数、循环次数
divDtocOvers:
pop ax
mov es:[bx+si],ah
inc si
loop divDtocOvers
add bx,32
pop si
pop cx
ret
;此函数将db型年份从data段移到table段的相应位置,仅移动
moveyear:
push ax
push bx
push cx
; push dx
; push ds
push si
push di
; push es
mov si,0 ;ds未变,还是data段
mov bx,0 ;es未变,还是指向table段
mov di,0
mov cx,21 ;21个数据
yearwai:
push cx
mov cx,4
yearnei:
mov al,ds:[si]
inc si
mov es:[bx+di],al
inc di
loop yearnei
add bx,32
mov di,0
pop cx
loop yearwai
; pop es
pop di
pop si
; pop ds
; pop dx
pop cx
pop bx
pop ax
ret
revenue:
;第二列收入转为十进制时,存在除法溢出问题,需要用公式
;X/N = int(H/N)*65536 + [rem(H/N)*65536+L]/N N是除数,X是被除数,H是X高位,L是X低位
push ax
push bx
push cx
push dx
push ds
push si
push di
push es
push bp
mov ax,data
mov ds,ax
mov si,84 ;全局变量
; mov ax,temp
; mov es,ax
; mov di,0
mov bx,8 ;全局变量,table中第8列开始
mov bp,0
mov cx,21
revenuewai:
push cx
mov ax,temp
mov es,ax
mov ax,ds:[si] ;低位在ax中
mov dx,ds:[si+2] ;高位在dx中
add si,4
;更新这两内存单元的值保证进入内层循环是分别存放计算的数据低、高位
mov es:[0],ax ;es:[0]始终存放着要计算数据的低位
mov es:[2],dx ;es:[2]始终存放着要计算数据的高位
revenuenei:
mov ax,es:[0]
mov dx,es:[2]
mov ax,dx ;被除数:dx存放高位,ax存放低位
mov dx,0
mov cx,10
div cx ;ax存放着商(高位),dx存放着余数
mov es:[2],ax ;商的高位
;对与右侧数据而言,余数dx的值为高位数据,L(原始被除数低16的值)
mov ax,es:[0] ;此时右侧数据,dx高位,ax低位
mov cx,10 ;每次div前,临时使用cx作为除数
div cx ;ax存放着商(低位),dx存放着余数
add dx,30h
push dx ;先将余数存起来
inc bp ;计算余数的个数
mov es:[0],ax ;商的低位
mov cx,ax
jcxz revenueneiOver
jmp revenuenei
revenueneiOver:
mov ax,table
mov es,ax
; mov bx,bx
mov di,0
mov cx,bp ;原始数据的位数
mov bp,0 ;bp的值忘记清零造成了巨大错误
revenueneiOvers:
pop ax
mov es:[bx+di],al
inc di
loop revenueneiOvers
add bx,32
pop cx
loop revenuewai
pop bp
pop es
pop di
pop si
pop ds
pop dx
pop cx
pop bx
pop ax
ret
;此函数将员工数复制到table中
;32位被除数除法运算,DX高位(0),AX低位,AX商,DX余数
employee:
push ax
push bx
push cx
push dx
push ds
push si
push di
push es
push bp
mov ax,data
mov ds,ax
mov si,168
mov ax,table
mov es,ax
mov bx,19
mov di,0
mov bp,0
mov cx,21
employeewai:
push cx
mov cx,0
mov ax,ds:[si]
add si,2
employeenei:
mov dx,0
mov cx,10
div cx
add dl,30h
push dx
inc bp
mov cx,ax
jcxz employeeneiOver
jmp short employeenei
employeeneiOver:
mov cx,bp
employeeneiOvers:
pop ax
mov es:[bx+di],al
inc di
loop employeeneiOvers
add bx,32
mov di,0
mov bp,0
pop cx
loop employeewai
pop bp
pop es
pop di
pop si
pop ds
pop dx
pop cx
pop bx
pop ax
ret
;将所有信息显示出来
showstr:
push ax
push bx
push cx
push dx
push ds
push si
push di
push es
push bp
mov ax,table
mov ds,ax
mov si,0
mov ax,0b800h
mov es,ax
mov bx,160*2+24*2
mov di,0
mov ah,00000010b
mov cx,21
showwai:
push cx
mov cx,32
shownei:
mov al,ds:[si]
inc si
mov es:[bx+di],ax
add di,2
loop shownei
add bx,160
mov di,0
pop cx
loop showwai
pop bp
pop es
pop di
pop si
pop ds
pop dx
pop cx
pop bx
pop ax
ret
code ends
end start
此代码在DOSBox中的运行结果: ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200412205234132.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NoYWNvXw==,size_16,color_FFFFFF,t_70)
|